home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJSRC111.ZIP / go32 / ed / debug.c < prev    next >
C/C++ Source or Header  |  1993-11-22  |  22KB  |  828 lines

  1. /* This is file DEBUG.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <setjmp.h>
  17. #include <math.h>
  18.  
  19. #include "ed.h"
  20. #include "unassmbl.h"
  21. #include "syms.h"
  22.  
  23. typedef struct {
  24.   word16 sig0;
  25.   word16 sig1;
  26.   word16 sig2;
  27.   word16 sig3;
  28.   word16 exponent:15;
  29.   word16 sign:1;
  30. } NPXREG;
  31.  
  32. typedef struct {
  33.   word32 control;
  34.   word32 status;
  35.   word32 tag;
  36.   word32 eip;
  37.   word32 cs;
  38.   word32 dataptr;
  39.   word32 datasel;
  40.   NPXREG reg[8];
  41. } NPX;
  42.  
  43. static char char32spc[] = "xxx·xxx·xxx·xxx∙xxx·xxx·xxx·xxx ";
  44.  
  45. static char flset[] = "VMRF  NT    OFDNIETFMIZR  AC  PE  CY";
  46. static char floff[] = "              UPID  PLNZ      PO  NC";
  47. static char fluse[] = {1,1,0,1,0,0,1,1,1,1,1,1,0,1,0,1,0,1};
  48. static NPX npx;
  49.  
  50. void save_npx(void)
  51. {
  52. asm(                                       "\n\
  53.     inb    $0xa0,%al                        \n\
  54.     testb    $0x20,%al                        \n\
  55.     jz    Lfclex_done                        \n\
  56.     xorl    %eax,%eax                        \n\
  57.     outb    %al,$0xf0                        \n\
  58.     movb    $0x20,%al                        \n\
  59.     outb    %al,$0xa0                        \n\
  60.     outb    %al,$0x20                        \n\
  61. Lfclex_done:                                \n\
  62.     movl    $_npx, %eax                        \n\
  63.     fnsave    (%eax)                            \n\
  64.     fwait                                "
  65. );
  66. }
  67.  
  68. void load_npx(void)
  69. {
  70. asm(                                       "\n\
  71.     movl    $_npx, %eax                        \n\
  72.     movb    $0,4(%eax)        /* clear pending exceptions */    \n\
  73.     frstor    (%eax)                            "
  74. );
  75. }
  76.  
  77. void tssprint(TSS *t)
  78. {
  79.   int i;
  80.   printf("eax=%08lx  ebx=%08lx  ecx=%08lx  edx=%08lx\n",
  81.     t->tss_eax, t->tss_ebx, t->tss_ecx, t->tss_edx);
  82.   printf("esi=%08lx  edi=%08lx  ebp=%08lx ",
  83.     t->tss_esi, t->tss_edi, t->tss_ebp);
  84.   for (i=0; i<18; i++)
  85.     if (fluse[i])
  86.       if (t->tss_eflags & (1<<(17-i)))
  87.         printf(" %2.2s", flset+i*2);
  88.       else
  89.         printf(" %2.2s", floff+i*2);
  90.   printf("\nds=%04x es=%04x fs=%04x gs=%04x ss:esp=%04x:%08lx cs=%04x\n",
  91.     t->tss_ds, t->tss_es, t->tss_fs, t->tss_gs, t->tss_ss, t->tss_esp, t->tss_cs);
  92. }
  93.  
  94. my_getline(char *buf, char *lasttoken)
  95. {
  96.   int idx, i, ch, erase_it=1;
  97.   unsigned char old_enable;
  98.  
  99.   ansi(A_green);
  100.   printf(">>");
  101.   ansi(A_green | A_bold);
  102.   printf(" %s", lasttoken);
  103.   for (i=0; lasttoken[i]; i++)
  104.     putchar(8);
  105.   ansi(A_white);
  106.   fflush(stdout);
  107.   idx = 0;
  108.  
  109.   while (1)
  110.   {
  111.     ch = getkey();
  112.     if (erase_it)
  113.     {
  114.       for (i=0; lasttoken[i]; i++)
  115.         putchar(' ');
  116.       for (i=0; lasttoken[i]; i++)
  117.         putchar(8);
  118.     }
  119.     switch (ch)
  120.     {
  121.       case 10:
  122.       case 13:
  123.         buf[idx] = 0;
  124.         if (!idx && lasttoken[0])
  125.           printf("\r  \r");
  126.         else
  127.           putchar('\n');
  128.         ansi(A_grey);
  129.         fflush(stdout);
  130.         return;
  131.       case 27:
  132.       case 21:
  133.         while (idx)
  134.         {
  135.           printf("\b \b");
  136.           idx--;
  137.         }
  138.         fflush(stdout);
  139.         break;
  140.       case 8:
  141.         if (idx)
  142.         {
  143.           printf("\b \b");
  144.           fflush(stdout);
  145.           idx--;
  146.         }
  147.         break;
  148.       default:
  149.         putchar(ch);
  150.         fflush(stdout);
  151.         buf[idx++] = ch;
  152.         break;
  153.     }
  154.   }
  155. }
  156.  
  157. typedef enum { Zero, Unknown, CONT, STEP, NEXT, REGS, SET, HELP, LIST,
  158. DUMP, PRINT, QUIT, BREAK, STATUS, WHERE, DUMP_A, DUMP_B, DUMP_W, WHEREIS, XNPX,
  159. CLS } COMMAND_TYPES;
  160.  
  161. extern struct {
  162.   char *name;
  163.   int size;
  164.   int ofs;
  165.   } regs[];
  166.  
  167.  
  168. typedef struct {
  169.         char *cp;
  170.         int t;
  171.         } item;
  172.  
  173. item cmds[] = {
  174.         "g", CONT,
  175.         "go", CONT,
  176.         "cont", CONT,
  177.         "c", CONT,
  178.         "step", STEP,
  179.         "s", STEP,
  180.         "next", NEXT,
  181.         "n", NEXT,
  182.         "regs", REGS,
  183.         "r", REGS,
  184.         "set", SET,
  185.         "help", HELP,
  186.         "h", HELP,
  187.         "?", HELP,
  188.         "list", LIST,
  189.         "l", LIST,
  190.         "u", LIST,
  191.         "dump", DUMP,
  192.         "d", DUMP,
  193.         "da", DUMP_A,
  194.         "db", DUMP_B,
  195.         "dw", DUMP_W,
  196.         "dd", DUMP,
  197.         "p", PRINT,
  198.         "print", PRINT,
  199.         "quit", QUIT,
  200.         "q", QUIT,
  201.         "break", BREAK,
  202.         "b", BREAK,
  203.         "bl", STATUS,
  204.         "status", STATUS,
  205.         "where", WHERE,
  206.         "whereis", WHEREIS,
  207.         "npx", XNPX,
  208.         "cls", CLS,
  209.         0, 0
  210.         };
  211.  
  212. #define dr0 edi.dr[0]
  213. #define dr1 edi.dr[1]
  214. #define dr2 edi.dr[2]
  215. #define dr3 edi.dr[3]
  216. #define dr4 edi.dr[4]
  217. #define dr5 edi.dr[5]
  218. #define dr6 edi.dr[6]
  219. #define dr7 edi.dr[7]
  220.  
  221. int can_longjmp = 0;
  222. jmp_buf debugger_jmpbuf;
  223.  
  224. int do_where(word32 vaddr)
  225. {
  226.   int i;
  227.   int32 delta;
  228.   char *name;
  229.   printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta));
  230.   name = syms_val2line(vaddr, &i, 0);
  231.   if (name)
  232.     printf(", line %d in file %s", i, name);
  233.   else if (delta)
  234.     printf("%+ld", delta);
  235.   putchar('\n');
  236.   return delta;
  237. }
  238.  
  239. debugger(void)
  240. {
  241.   char buf[140], token[10];
  242.   char buf2[140], *name, lasttoken[140];
  243.   int i, n, s, len, rem_cmd, cmd, vstep, found;
  244.   word32 vaddr, v, rem_v, olddr7;
  245.   int32 delta;
  246.  
  247.   dr0 = dr1 = dr2 = edi.app_base;
  248.   dr3 = syms_name2val("_main") + edi.app_base;
  249.   if (undefined_symbol)
  250.     dr3 = a_tss.tss_eip + edi.app_base;
  251.   can_longjmp = 1;
  252.   setjmp(debugger_jmpbuf);
  253.   rem_cmd = Zero;
  254.   lasttoken[0] = 0;
  255.   while (1)
  256.   {
  257.     int found;
  258.     undefined_symbol = 0;
  259.     my_getline(buf, lasttoken);
  260.     token[0] = 0;
  261.     if (sscanf(buf, "%s %[^\n]", token, buf) < 2)
  262.       buf[0] = 0;
  263.     if (token[0])
  264.       strcpy(lasttoken, token);
  265.     cmd = rem_cmd;
  266.     found = 0;
  267.     for (i=0; cmds[i].cp; i++)
  268.       if (strcmp(cmds[i].cp, token) == 0)
  269.       {
  270.         cmd = cmds[i].t;
  271.         found = 1;
  272.       }
  273.     if (!found && token[0])
  274.       cmd = Unknown;
  275.     if (rem_cmd != cmd)
  276.       vaddr = a_tss.tss_eip;
  277.  
  278.     switch (cmd)
  279.     {
  280.       case HELP:
  281.         printf("Commands:\n");
  282.         printf("go <v>\tg\tgo, stop at <v>\n");
  283.         printf("cont\tc\tcontinue execution\n");
  284.         printf("step\ts\tstep through current instruction\n");
  285.         printf("next\tn\tstep to next instruction\n");
  286.         printf("list\tl u\tlist instructions (takes addr, count)\n");
  287.         printf("dump\td\tdump memory (takes addr, count)\n");
  288.         printf("print\tp\tprint value of expression (takes expr)\n");
  289.         printf("break\tb\tset breakpoint (takes which, addr)\n");
  290.         printf("status\t\tbreakpoint status\n");
  291.         printf("regs\tr\tprint registers\n");
  292.         printf("set\t\tset register/memory\n");
  293.         printf("npx\t\tdisplay 80387 contents\n");
  294.         printf("where\t\tdisplay list of active functions\n");
  295.         printf("whereis\t\tfind a symbol/location (takes wildcard or value)\n");
  296.         printf("cls\t\tclear screen\n");
  297.         printf("help\th,?\tprint help\n");
  298.         printf("quit\tq\tquit\n");
  299.         break;
  300.  
  301.       case CONT:
  302.         sscanf(buf, "%s", buf);
  303.         if (buf[0])
  304.         {
  305.           v = syms_name2val(buf);
  306.           if (undefined_symbol)
  307.             break;
  308.           dr3 = v + edi.app_base;
  309.           dr7 |= 0xc0;
  310.         }
  311.         else
  312.           dr7 &= ~0xc0;
  313.         olddr7 = dr7;
  314.         dr7 = 0;
  315.         a_tss.tss_eflags |= 0x0100;
  316.         run_child();
  317.         dr7 = olddr7;
  318.         if (a_tss.tss_irqn == 1)
  319.         {
  320.           a_tss.tss_eflags &= ~0x0100;
  321.           a_tss.tss_eflags |= 0x10000;
  322.           run_child();
  323.           if (a_tss.tss_irqn == 1)
  324.             tssprint(&a_tss);
  325.         }
  326.         print_reason();
  327.         dr3 = unassemble(a_tss.tss_eip, 1) + edi.app_base;
  328.         break;
  329.  
  330.       case STEP:
  331.         if (rem_cmd != cmd)
  332.           n = 1;
  333.         sscanf(buf, "%d", &n);
  334.         a_tss.tss_eflags |= 0x0100;
  335.         for (i=0; i<n; i++)
  336.         {
  337.           int q;
  338.           olddr7 = dr7;
  339.           dr7 = 0;
  340.           run_child();
  341.           dr7 = olddr7;
  342.           q = print_reason();
  343.           dr3 = unassemble(a_tss.tss_eip, 1) + edi.app_base;
  344.           if ((a_tss.tss_irqn != 1) || q)
  345.             break;
  346.         }
  347.         a_tss.tss_eflags &= ~0x0100;
  348.         break;
  349.  
  350.       case NEXT:
  351.         if (rem_cmd != cmd)
  352.           n = 1;
  353.         sscanf(buf, "%d", &n);
  354.         for (i=0; i<n; i++)
  355.         {
  356.           olddr7 = dr7;
  357.           dr7 &= ~0xc0;
  358.           dr7 |= 0xc0;
  359.           if (last_unassemble_unconditional ||
  360.               last_unassemble_jump)
  361.             a_tss.tss_eflags |= 0x0100; /* step */
  362.           else
  363.             a_tss.tss_eflags &= ~0x0100;
  364.           run_child();
  365.           dr7 = olddr7;
  366.           print_reason();
  367.           dr3 = unassemble(a_tss.tss_eip, 1) + edi.app_base;
  368.           if (a_tss.tss_irqn != 1)
  369.             break;
  370.         }
  371.         a_tss.tss_eflags &= ~0x0100;
  372.         break;
  373.  
  374.       case WHERE:
  375.         lasttoken[0] = 0;
  376.         v = a_tss.tss_ebp;
  377.         vaddr = a_tss.tss_eip;
  378.         delta = do_where(vaddr);
  379.         if (delta == 0) /* try to find out where we just came from */
  380.         {
  381.           read_child(a_tss.tss_esp, &rem_v, 4);
  382.           if (rem_v)
  383.             do_where(rem_v);
  384.         }
  385.         do {
  386.           if (v == 0)
  387.             break;
  388.           if (read_child(v, &rem_v, 4))
  389.             break;
  390.           if (rem_v == 0)
  391.             break;
  392.           if (read_child(v+4, &vaddr, 4))
  393.             break;
  394.           do_where(vaddr);
  395.           v = rem_v;
  396.         } while ((v>=a_tss.tss_esp) && (v<0x80000000L));
  397.         break;
  398.  
  399.       case WHEREIS:
  400.         lasttoken[0] = 0;
  401.         sscanf(buf, "%s", buf2);
  402.         if (strpbrk(buf2, "*?"))
  403.         {
  404.           syms_listwild(buf2);
  405.           break;
  406.         }
  407.         if (buf2[0])
  408.           vaddr = syms_name2val(buf2);
  409.         if (undefined_symbol)
  410.           break;
  411.         name = syms_val2name(vaddr, &delta);
  412.         printf("0x%08lx %s", vaddr, name);
  413.         if (delta)
  414.           printf("+%lx", delta);
  415.         name = syms_val2line(vaddr, &i, 0);
  416.         if (name)
  417.           printf(", line %d in file %s", i, name);
  418.         putchar('\n');
  419.         break;
  420.  
  421.       case LIST:
  422.         if (rem_cmd != cmd)
  423.           n = 10;
  424.         buf2[0] = 0;
  425.         sscanf(buf, "%s %d", buf2, &n);
  426.         if (buf2[0] && strcmp(buf2, "."))
  427.           vaddr = syms_name2val(buf2);
  428.         if (undefined_symbol)
  429.           break;
  430.         for (i=0; i<n; i++)
  431.         {
  432.           vaddr = unassemble(vaddr, 0);
  433.           i += last_unassemble_extra_lines;
  434.         }
  435.         break;
  436.  
  437.       case DUMP_A:
  438.         buf2[0] = 0;
  439.         sscanf(buf, "%s %d", buf2, &n);
  440.         if (buf2[0])
  441.           vaddr = syms_name2val(buf2);
  442.         if (undefined_symbol)
  443.           break;
  444.         while (1)
  445.         {
  446.           word8 ch;
  447.           if (vaddr == 0)
  448.           {
  449.             printf("<bad address>\n");
  450.             break;
  451.           }
  452.           if (read_child(vaddr, &ch, 1))
  453.             break;
  454.           if (ch == 0)
  455.           {
  456.             putchar('\n');
  457.             break;
  458.           }
  459.           if (ch < ' ')
  460.             printf("^%c", ch+'@');
  461.           else if ((ch >= ' ') && (ch < 0x7f))
  462.             putchar(ch);
  463.           else if (ch == 0x7f)
  464.             printf("^?");
  465.           else if ((ch >= 0x80) && (ch < 0xa0))
  466.             printf("M-^%c", ch-0x80+'@');
  467.           else if (ch >= 0xa0)
  468.             printf("M-%c", ch-0x80);
  469.           vaddr++;
  470.         }
  471.         break;
  472.       case DUMP:
  473.       case DUMP_B:
  474.       case DUMP_W:
  475.         if (rem_cmd != cmd)
  476.           n = 4;
  477.         buf2[0] = 0;
  478.         sscanf(buf, "%s %d", buf2, &n);
  479.         if (buf2[0])
  480.           vaddr = syms_name2val(buf2);
  481.         if (undefined_symbol)
  482.         {
  483.           printf("undefined symbol\n");
  484.           break;
  485.         }
  486.         s = 0;
  487.         len = n + (~((vaddr&15)/4-1) & 3);
  488.         for (i=-((vaddr&15)/4); i<len; i++)
  489.         {
  490.           if ((s&3) == 0)
  491.             printf("0x%08lx:", vaddr+i*4);
  492.           if ((i>=0) && (i<n))
  493.           {
  494.             word32 v;
  495.             if (read_child(vaddr+i*4, &v, 4))
  496.               break;
  497.             printf(" 0x%08lx", v);
  498.           }
  499.           else
  500.             printf("           ");
  501.           if ((s & 3) == 3)
  502.           {
  503.             int j, c;
  504.             printf("  ");
  505.             for (j=0; j<16; j++)
  506.               if ((j+i*4-12>=0) && (j+i*4-12 < n*4))
  507.               {
  508.                 if (read_child(vaddr+j+i*4-12, &c, 1))
  509.                   break;
  510.                 if (c<' ')
  511.                   putchar('.');
  512.                 else
  513.                   putchar(c);
  514.               }
  515.               else
  516.                 putchar(' ');
  517.             printf("\n");
  518.           }
  519.           s++;
  520.         }
  521.         if (s & 3)
  522.           printf("\n");
  523.         vaddr += n*4;
  524.         break;
  525.  
  526.       case PRINT:
  527.         lasttoken[0] = 0;
  528.         sscanf(buf, "%s", buf2);
  529.         if (buf2[0])
  530.           vaddr = syms_name2val(buf2);
  531.         if (undefined_symbol)
  532.           break;
  533.         name = syms_val2name(vaddr, &delta);
  534.         printf("0x%08lx %ld", vaddr, (long)vaddr);
  535.         for (i=31; i>=0; i--)
  536.         {
  537.           if (char32spc[i] != 'x')
  538.             putchar(char32spc[i]);
  539.           printf("%d", (int)((vaddr>>i)&1));
  540.         }
  541.         printf("\n");
  542.         break;
  543.  
  544.       case BREAK:
  545.         vaddr = n = 0;
  546.         buf2[0] = 0;
  547.         sscanf(buf, "%d %s", &n, buf2);
  548.         if (buf2[0])
  549.           vaddr = syms_name2val(buf2);
  550.         if (undefined_symbol)
  551.           break;
  552.         edi.dr[n] = vaddr + edi.app_base;
  553.         if (vaddr == 0)
  554.           dr7 &= ~(2 << (n*2));
  555.         else
  556.           dr7 |= 2 << (n*2);
  557.  
  558.       case STATUS:
  559.         s = 0;
  560.         for (n=0; n<4; n++)
  561.         {
  562.           s = 1;
  563.           name = syms_val2name(edi.dr[n] - edi.app_base, &delta);
  564.           printf("  dr%d  %s", n, name);
  565.           if (delta)
  566.             printf("+%#lx", delta);
  567.           if (name[0] != '0')
  568.             printf(" (0x%lx)", edi.dr[n] - edi.app_base);
  569.           if (!(dr7 & (3 << (n*2))))
  570.             printf(" (disabled)");
  571.           putchar('\n');
  572.         }
  573.         if (s == 0)
  574.           printf("  No breakpoints set\n");
  575.         break;
  576.  
  577.       case REGS:
  578.         tssprint(&a_tss);
  579.         unassemble(a_tss.tss_eip, 0);
  580.         break;
  581.  
  582.       case SET:
  583.         cmd = Zero;
  584.         lasttoken[0] = 0;
  585.         buf2[0] = 0;
  586.         len = sscanf(buf, "%s %s", buf2, buf);
  587.         if (buf2[0] == 0)
  588.         {
  589.           break;
  590.         }
  591.         if (len > 1)
  592.         {
  593.           v = syms_name2val(buf);
  594.           if (undefined_symbol)
  595.             break;
  596.         }
  597.         found = 0;
  598.         for (i=0; regs[i].name; i++)
  599.           if (strcmp(regs[i].name, buf2) == 0)
  600.           {
  601.             TSS *tss_ptr = &a_tss;
  602.             found = 1;
  603.             if (len > 1)
  604.             {
  605.               switch (regs[i].size)
  606.               {
  607.                 case 1:
  608.                   *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  609.                   break;
  610.                 case 2:
  611.                   *(word16 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  612.                   break;
  613.                 case 4:
  614.                   *(word32 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  615.                   break;
  616.               }
  617.             }
  618.             else
  619.             {
  620.               switch (regs[i].size)
  621.               {
  622.                 case 1:
  623.                   printf("%02x ", *(word8 *)((word8 *)tss_ptr + regs[i].ofs));
  624.                   my_getline(buf, "");
  625.                   if (buf[0])
  626.                   {
  627.                     v = syms_name2val(buf);
  628.                     if (undefined_symbol)
  629.                       break;
  630.                     *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  631.                   }
  632.                   break;
  633.                 case 2:
  634.                   printf("%04x ", *(word16 *)((word16 *)tss_ptr + regs[i].ofs));
  635.                   my_getline(buf, "");
  636.                   if (buf[0])
  637.                   {
  638.                     v = syms_name2val(buf);
  639.                     if (undefined_symbol)
  640.                       break;
  641.                     *(word16 *)((word16 *)tss_ptr + regs[i].ofs) = v;
  642.                   }
  643.                   break;
  644.                 case 4:
  645.                   printf("%08lx ", *(word32 *)((word32 *)tss_ptr + regs[i].ofs));
  646.                   my_getline(buf, "");
  647.                   if (buf[0])
  648.                   {
  649.                     v = syms_name2val(buf);
  650.                     if (undefined_symbol)
  651.                       break;
  652.                     *(word32 *)((word32 *)tss_ptr + regs[i].ofs) = v;
  653.                   }
  654.                   break;
  655.               }
  656.             }
  657.             break;
  658.           }
  659.         if (found)
  660.           break;
  661.         vaddr = syms_name2val(buf2);
  662.         if (undefined_symbol)
  663.           break;
  664.         if (len < 2)
  665.         {
  666.           v = syms_name2val(buf);
  667.           if (undefined_symbol)
  668.             break;
  669.           write_child(vaddr, &v, 4);
  670.         }
  671.         while (1)
  672.         {
  673.           word32 vv;
  674.           if (read_child(vaddr, &vv,4))
  675.             break;
  676.           printf("0x%08lx 0x%08lx", vaddr, vv);
  677.           my_getline(buf, "");
  678.           if (buf[0])
  679.           {
  680.             word32 vv;
  681.             if (strcmp(buf, ".") == 0)
  682.               break;
  683.             vv = syms_name2val(buf);
  684.             if (write_child(vaddr, &vv, 4))
  685.               break;
  686.           }
  687.           vaddr += 4;
  688.         }
  689.         break;
  690.       case XNPX:
  691.         save_npx();
  692.         printf("Control: 0x%04lx  Status: 0x%04lx  Tag: 0x%04lx\n",
  693.                npx.control & 0xffff, npx.status & 0xffff, npx.tag & 0xffff);
  694.         for (i=0; i<8; i++)
  695.         {
  696.           double d;
  697.           int tag;
  698.           int tos = (npx.status >> 11) & 7;
  699.           printf("st(%d)  ", i);
  700.           if (npx.reg[i].sign)
  701.             putchar('-');
  702.           else
  703.             putchar('+');
  704.           printf(" %04x %04x %04x %04x e %04x    ",
  705.                  npx.reg[i].sig3,
  706.                  npx.reg[i].sig2,
  707.                  npx.reg[i].sig1,
  708.                  npx.reg[i].sig0,
  709.                  npx.reg[i].exponent);
  710.           tag = (npx.tag >> (((i+tos)%8)*2)) & 3;
  711.           switch (tag)
  712.           {
  713.             case 0:
  714.               printf("Valid");
  715.               if (((int)npx.reg[i].exponent-16382 < 1000) &&
  716.                   ((int)npx.reg[i].exponent-16382 > -1000))
  717.               {
  718.                 d = npx.reg[i].sig3/65536.0 + npx.reg[i].sig2/65536.0/65536.0
  719.                   + npx.reg[i].sig1/65536.0/65536.0/65536.0;
  720.                 d = ldexp(d,(int)npx.reg[i].exponent-16382);
  721.                 if (npx.reg[i].sign)
  722.                   d = -d;
  723.                 printf("  %.16g", d);
  724.               }
  725.               else
  726.                 printf("  (too big to display)");
  727.               putchar('\n');
  728.               break;
  729.             case 1:
  730.               printf("Zero\n");
  731.               break;
  732.             case 2:
  733.               printf("Special\n");
  734.               break;
  735.             case 3:
  736.               printf("Empty\n");
  737.               break;
  738.           }
  739.         }
  740.         load_npx();
  741.         break;
  742.  
  743.       case QUIT:
  744.         return;
  745.  
  746.       case Zero:
  747.         break;
  748.  
  749.       case CLS:
  750.     asm volatile("pusha; movb $15,%ah; int $0x10; movb $0,%ah; int $0x10; popa");
  751.     break;
  752.  
  753.       default:
  754.         printf("Unknown command\n");
  755.         lasttoken[0] = 0;
  756.         cmd = Zero;
  757.         break;
  758.     }
  759.     if (undefined_symbol)
  760.     {
  761.       lasttoken[0] = 0;
  762.       cmd = Zero;
  763.       undefined_symbol = 0;
  764.     }
  765.     rem_cmd = cmd;
  766.   }
  767. }
  768.  
  769. int print_reason(void)
  770. {
  771.   int n, i, rv=0;
  772.   i = a_tss.tss_irqn;
  773.   if ((i == 0x21) && ((a_tss.tss_eax & 0xff00) == 0x4c00))
  774.   {
  775.     ansi(A_green|A_bold);
  776.     printf("Program terminated normally, exit code is %d\n", (word8)a_tss.tss_eax);
  777.     a_tss.tss_eip -= 2; /* point to int 21h */
  778.     return 1;
  779.   }
  780.   ansi(A_red | A_bold);
  781.   if (i != 1)
  782.   {
  783.     tssprint(&a_tss);
  784.     if (i == 0x79)
  785.       printf("Keyboard interrupt\n");
  786.     else if (i == 0x75)
  787.     {
  788.       save_npx();
  789.       printf("Numeric Exception (");
  790.       if ((npx.status & 0x0241) == 0x0241)
  791.         printf("stack overflow");
  792.       else if ((npx.status & 0x0241) == 0x0041)
  793.         printf("stack underflow");
  794.       else if (npx.status & 1)
  795.         printf("invalid operation");
  796.       else if (npx.status & 2)
  797.         printf("denormal operand");
  798.       else if (npx.status & 4)
  799.         printf("divide by zero");
  800.       else if (npx.status & 8)
  801.         printf("overflow");
  802.       else if (npx.status & 16)
  803.         printf("underflow");
  804.       else if (npx.status & 32)
  805.         printf("loss of precision");
  806.       printf(") at eip=0x%08lx\n", npx.eip);
  807.       unassemble(npx.eip, 0);
  808.       load_npx();
  809.     }
  810.     else
  811.     {
  812.       printf("exception %d (%#02x) occurred", i, i);
  813.       if ((i == 8) || ((i>=10) && (i<=14)))
  814.         printf(", error code=%#lx", a_tss.tss_error);
  815.       putchar('\n');
  816.       rv = 1;
  817.     }
  818.   }
  819.   ansi(A_cyan | A_bold);
  820.   for (n=0; n<3; n++)
  821.     if ((dr6 & (1<<n)) && (dr7 & (3<<(n*2))))
  822.     {
  823.       printf("breakpoint %d hit\n", n);
  824.       rv = 1;
  825.     }
  826.   return rv;
  827. }
  828.